package com.plug.common.jdbc;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

/**
 * Created by slaye on 2016/12/16.
 */
public class DBConnectionManager {
    final Logger logger = LoggerFactory.getLogger(getClass());//日志实例
    static private DBConnectionManager instance;// 唯一数据库连接池管理实例类
    static private int clients; // 客户连接数
    private Vector drivers = new Vector();// 驱动信息
    private Hashtable pools = new Hashtable();// 连接池

    /**
     *
     * @类名：DBConnectionManager.java
     * @描述：管理类构造方法
     */
    private DBConnectionManager() {
    }

    /**
     *
     * 函数功能说明:得到管理类的唯一实例
     * @return
     * @return DBConnectionManager
     * @throws
     */
    public static synchronized DBConnectionManager getInstance() {
        if (instance == null) {
            instance = new DBConnectionManager();
        }
        return instance;
    }

    /**
     *
     * 函数功能说明:释放连接
     * @param name 数据连接池名称
     * @param con 待释放的连接
     * @return void
     * @throws
     */
    public void freeConnection(String name, Connection con) {
        DBConnectionPool pool = (DBConnectionPool) pools.get(name);// 根据关键名字得到连接池
        logger.debug("释放{}连接池连接.",name);
        if (pool != null) {
            pool.freeConnection(con);// 释放连接
        }
    }

    /**
     *
     * 函数功能说明:根据连接池的名字name得到一个连接
     * @param name 连接池的名字
     * @return
     * @return Connection 数据库连接
     * @throws
     */
    public Connection getConnection(String name) {
        DBConnectionPool pool = null;
        Connection con = null;
        pool = (DBConnectionPool) pools.get(name);// 从名字中获取连接池
        con = pool.getConnection();// 从选定的连接池中获得连接
        if (con != null) {
            System.out.println("得到连接。。。");
        }
        return con;
    }

    /**
     *
     * 函数功能说明:根据连接池的名字name得到一个连接
     * @param jdbcInfoBean 对象
     * @return
     * @return Connection 数据库连接
     * @throws
     */
    public Connection getConnection(JDBCInfoBean jdbcInfoBean) {
        DBConnectionPool pool = null;
        Connection con = null;
        pool = (DBConnectionPool) pools.get(jdbcInfoBean.getName());// 从名字中获取连接池
        if(pool != null) {
            con = pool.getConnection();// 从选定的连接池中获得连接
            if (con == null) {
                this.createPools(jdbcInfoBean);
                pool = (DBConnectionPool) pools.get(jdbcInfoBean.getName());// 从名字中获取连接池
                con = pool.getConnection();
            }
        } else {
            this.createPools(jdbcInfoBean);
            pool = (DBConnectionPool) pools.get(jdbcInfoBean.getName());// 从名字中获取连接池
            con = pool.getConnection();
        }
        try {
            if(con.isClosed()){
                pools.remove(jdbcInfoBean.getName());
                this.createPools(jdbcInfoBean);
                pool = (DBConnectionPool) pools.get(jdbcInfoBean.getName());// 从名字中获取连接池
                con = pool.getConnection();
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return con;
    }

    /**
     *
     * 函数功能说明:释放所有连接
     * @return void
     * @throws
     */
    public synchronized void release() {
        Enumeration allpools = pools.elements();
        while (allpools.hasMoreElements()) {
            DBConnectionPool pool = (DBConnectionPool) allpools.nextElement();
            if (pool != null) {
                pool.release();
            }
        }
        pools.clear();
    }

    /**
     *
     * 函数功能说明:根据jdbc连接信息，创建一个连接池
     * @param info jdbc连接信息
     * @return void
     * @throws
     */
    public void createPools(JDBCInfoBean info) {
        DBConnectionPool dbpool = new DBConnectionPool();
        dbpool.setName(info.getName());
        dbpool.setDriver(info.getDriver());
        dbpool.setUrl(info.getUrl());
        dbpool.setUser(info.getUsername());
        dbpool.setPassword(info.getPassword());
        dbpool.setMaxConn(1000);
        System.out.println("ioio:" + info.getName());
        pools.put(info.getName(), dbpool);
    }


    /**
     *
     * 函数功能说明:初始化连接池的参数
     * @return void
     * @throws
     */
    private void init() {
        // 加载驱动程序
        this.loadDrivers();
        // 创建连接池
        Iterator alldriver = drivers.iterator();
        while (alldriver.hasNext()) {
            this.createPools((JDBCInfoBean) alldriver.next());
            System.out.println("创建连接池。。。");
        }
        System.out.println("创建连接池完毕。。。");
    }

    /**
     *
     * 函数功能说明:加载jdbc连接信息
     * @return void
     * @throws
     */
    private void loadDrivers() {
        Properties pro = new Properties();
        try {
            pro.load(this.getClass().getResourceAsStream("/jdbc.properties"));
            JDBCInfoBean plugInfo = new JDBCInfoBean();
            plugInfo.setName("plug");
            plugInfo.setDriver(pro.getProperty("driver"));
            plugInfo.setUsername(pro.getProperty("username"));
            plugInfo.setPassword(pro.getProperty("password"));
            plugInfo.setUrl(pro.getProperty("url"));
            drivers.add(plugInfo);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     *
     * 函数功能说明:测试程序
     * @return void
     * @throws
     */
    public static void main(String[] args) {
        DBConnectionManager dbc = DBConnectionManager.getInstance();
        new DBConnectionManager();
        JDBCInfoBean jdbcInfoBean = new JDBCInfoBean();
        jdbcInfoBean.setName("plug");
        jdbcInfoBean.setDriver("com.mysql.jdbc.Driver");
        jdbcInfoBean.setPassword("123");
        jdbcInfoBean.setUrl("jdbc:mysql://localhost:3306/test");
        jdbcInfoBean.setUsername("root");
        dbc.createPools(jdbcInfoBean);
        Connection con = dbc.getConnection("plug");
        if (con != null) {
            try {
                con.setAutoCommit(false);
                ResultSet rs = con.createStatement().executeQuery("select t.* from user_test t");
                while (rs.next()) {
                    System.out.println(rs.getString(1));
                    System.out.println(rs.getString(2));
                }

            } catch (SQLException e) {
                e.printStackTrace();
            }
            System.out.println();
        }
        dbc.freeConnection("plug", con);
        dbc.release();
    }
}
